border-image: add support for border-image-width too
authorCosimo Cecchi <cosimoc@gnome.org>
Thu, 9 Jun 2011 23:59:14 +0000 (19:59 -0400)
committerCosimo Cecchi <cosimoc@gnome.org>
Fri, 10 Jun 2011 00:01:57 +0000 (20:01 -0400)
It's useful to set a slice size != border-width, as backgrounds are
clipped to border-width too.

As slices can be half-transparent and overlap the background,
this would not fill the border box properly if we only use a single
property for specifying the width.

Also, this brings us even closer to CSS3.

gtk/gtkborderimage.c
gtk/gtkborderimageprivate.h
gtk/gtkcssprovider.c
gtk/gtkstyleproperty.c

index f259310c8fd1bb2e5247a80e8f14c85a3bf7101f..f5cca50dfe5e3206a224333ac542834820430fdb 100644 (file)
@@ -52,14 +52,16 @@ struct _GtkBorderImage {
   GtkGradient *source_gradient;
 
   GtkBorder slice;
+  GtkBorder *width;
   GtkCssBorderImageRepeat repeat;
 
   gint ref_count;
 };
 
 GtkBorderImage *
-_gtk_border_image_new (cairo_pattern_t      *pattern,
-                       GtkBorder            *slice,
+_gtk_border_image_new (cairo_pattern_t         *pattern,
+                       GtkBorder               *slice,
+                       GtkBorder               *width,
                        GtkCssBorderImageRepeat *repeat)
 {
   GtkBorderImage *image;
@@ -73,6 +75,9 @@ _gtk_border_image_new (cairo_pattern_t      *pattern,
   if (slice != NULL)
     image->slice = *slice;
 
+  if (width != NULL)
+    image->width = gtk_border_copy (width);
+
   if (repeat != NULL)
     image->repeat = *repeat;
 
@@ -80,8 +85,9 @@ _gtk_border_image_new (cairo_pattern_t      *pattern,
 }
 
 GtkBorderImage *
-_gtk_border_image_new_for_gradient (GtkGradient          *gradient,
-                                    GtkBorder            *slice,
+_gtk_border_image_new_for_gradient (GtkGradient             *gradient,
+                                    GtkBorder               *slice,
+                                    GtkBorder               *width,
                                     GtkCssBorderImageRepeat *repeat)
 {
   GtkBorderImage *image;
@@ -95,6 +101,9 @@ _gtk_border_image_new_for_gradient (GtkGradient          *gradient,
   if (slice != NULL)
     image->slice = *slice;
 
+  if (width != NULL)
+    image->width = gtk_border_copy (width);
+
   if (repeat != NULL)
     image->repeat = *repeat;
 
@@ -126,6 +135,9 @@ _gtk_border_image_unref (GtkBorderImage *image)
       if (image->source_gradient != NULL)
         gtk_gradient_unref (image->source_gradient);
 
+      if (image->width != NULL)
+        gtk_border_free (image->width);
+
       g_slice_free (GtkBorderImage, image);
     }
 }
@@ -134,7 +146,7 @@ GParameter *
 _gtk_border_image_unpack (const GValue *value,
                           guint        *n_params)
 {
-  GParameter *parameter = g_new0 (GParameter, 3);
+  GParameter *parameter = g_new0 (GParameter, 4);
   GtkBorderImage *image = g_value_get_boxed (value);
 
   parameter[0].name = "border-image-source";
@@ -146,14 +158,18 @@ _gtk_border_image_unpack (const GValue *value,
   parameter[2].name = "border-image-repeat";
   g_value_init (&parameter[2].value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
 
+  parameter[3].name = "border-image-width";
+  g_value_init (&parameter[3].value, GTK_TYPE_BORDER);
+
   if (image != NULL)
     {
       g_value_set_boxed (&parameter[0].value, image->source);
       g_value_set_boxed (&parameter[1].value, &image->slice);
       g_value_set_boxed (&parameter[2].value, &image->repeat);
+      g_value_set_boxed (&parameter[3].value, image->width);
     }
 
-  *n_params = 3;
+  *n_params = 4;
   return parameter;
 }
 
@@ -164,13 +180,14 @@ _gtk_border_image_pack (GValue             *value,
 {
   GtkBorderImage *image;
   cairo_pattern_t *source;
-  GtkBorder *slice;
+  GtkBorder *slice, *width;
   GtkCssBorderImageRepeat *repeat;
 
   gtk_style_properties_get (props, state,
                             "border-image-source", &source,
                             "border-image-slice", &slice,
                             "border-image-repeat", &repeat,
+                            "border-image-width", &width,
                             NULL);
 
   if (source == NULL)
@@ -179,7 +196,7 @@ _gtk_border_image_pack (GValue             *value,
     }
   else
     {
-      image = _gtk_border_image_new (source, slice, repeat);
+      image = _gtk_border_image_new (source, slice, width, repeat);
       g_value_take_boxed (value, image);
 
       cairo_pattern_destroy (source);
@@ -188,6 +205,9 @@ _gtk_border_image_pack (GValue             *value,
   if (slice != NULL)
     gtk_border_free (slice);
 
+  if (width != NULL)
+    gtk_border_free (width);
+
   if (repeat != NULL)
     g_free (repeat);
 }
@@ -370,6 +390,9 @@ _gtk_border_image_render (GtkBorderImage   *image,
   int surface_width, surface_height;
   int h, v;
 
+  if (image->width != NULL)
+    border_width = image->width;
+
   if (cairo_pattern_get_type (image->source) != CAIRO_PATTERN_TYPE_SURFACE)
     {
       cairo_matrix_t matrix;
@@ -437,7 +460,6 @@ _gtk_border_image_render (GtkBorderImage   *image,
                                                       horizontal_slice[h].size,
                                                       vertical_slice[v].size);
 
-          /* xxx: we scale to border-width here, that's wrong, isn't it? */
           gtk_border_image_render_slice (cr,
                                          slice,
                                          horizontal_slice[h].size,
index ca2ef0164951af705c104931ae61724d253f7977..585be67985478c7975398753fb3de25c41e8365b 100644 (file)
@@ -40,9 +40,11 @@ GType             _gtk_border_image_get_type         (void) G_GNUC_CONST;
 
 GtkBorderImage *  _gtk_border_image_new              (cairo_pattern_t      *source,
                                                       GtkBorder            *slice,
+                                                      GtkBorder            *width,
                                                       GtkCssBorderImageRepeat *repeat);
 GtkBorderImage *  _gtk_border_image_new_for_gradient (GtkGradient          *gradient,
                                                       GtkBorder            *slice,
+                                                      GtkBorder            *width,
                                                       GtkCssBorderImageRepeat *repeat);
 
 GtkBorderImage *  _gtk_border_image_ref              (GtkBorderImage       *image);
index 42a25a96c914397e663ab74922da6f21c57f1ccd..4258b3e7761abc1eef1320531f858b9b55311644 100644 (file)
  * <inlinegraphic fileref="slices.png" format="PNG"/>
  * <para>
  * The parameters of the slicing process are controlled by
- * three separate properties. Note that you can use the
+ * four separate properties. Note that you can use the
  * <literallayout>border-image</literallayout> shorthand property
  * to set values for the three properties at the same time.
  * </para>
  * of the border.
  * </para>
  * <para>
+ * <literallayout>border-image-width: @top @right @bottom @left</literallayout>
+ * The sizes specified by the @top, @right, @bottom and @left parameters
+ * are inward distances from the border box edge, used to specify the
+ * rendered size of each slice determined by border-image-slice.
+ * If this property is not specified, the values of border-width will
+ * be used as a fallback.
+ * </para>
+ * <para>
  * <literallayout>border-image-repeat: [stretch|repeat|round|space] ? 
  * [stretch|repeat|round|space]</literallayout>
  * Specifies how the image slices should be rendered in the area
index 7a93c6a19c5d1c8152107c170b7f4593106b53b0..ce2f4e1fafed15186839f783216c34ff1bf7e6de 100644 (file)
@@ -1023,7 +1023,7 @@ border_image_value_parse (GtkCssParser *parser,
   GValue temp = { 0, };
   cairo_pattern_t *pattern = NULL;
   GtkGradient *gradient = NULL;
-  GtkBorder border, *parsed_border;
+  GtkBorder slice, *width = NULL, *parsed_slice;
   GtkCssBorderImageRepeat repeat, *parsed_repeat;
   gboolean retval = FALSE;
   GtkBorderImage *image = NULL;
@@ -1044,8 +1044,19 @@ border_image_value_parse (GtkCssParser *parser,
   if (!border_value_parse (parser, base, &temp))
     goto out;
 
-  parsed_border = g_value_get_boxed (&temp);
-  border = *parsed_border;
+  parsed_slice = g_value_get_boxed (&temp);
+  slice = *parsed_slice;
+
+  if (_gtk_css_parser_try (parser, "/", TRUE))
+    {
+      g_value_unset (&temp);
+      g_value_init (&temp, GTK_TYPE_BORDER);
+
+      if (!border_value_parse (parser, base, &temp))
+        goto out;
+
+      width = g_value_dup_boxed (&temp);
+    }
 
   g_value_unset (&temp);
   g_value_init (&temp, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
@@ -1059,9 +1070,9 @@ border_image_value_parse (GtkCssParser *parser,
   g_value_unset (&temp);
 
   if (gradient != NULL)
-    image = _gtk_border_image_new_for_gradient (gradient, &border, &repeat);
+    image = _gtk_border_image_new_for_gradient (gradient, &slice, width, &repeat);
   else if (pattern != NULL)
-    image = _gtk_border_image_new (pattern, &border, &repeat);
+    image = _gtk_border_image_new (pattern, &slice, width, &repeat);
 
   if (image != NULL)
     {
@@ -1076,6 +1087,9 @@ border_image_value_parse (GtkCssParser *parser,
   if (gradient != NULL)
     gtk_gradient_unref (gradient);
 
+  if (width != NULL)
+    gtk_border_free (width);
+
   return retval;
 }
 
@@ -2231,6 +2245,11 @@ gtk_style_property_init (void)
                                                               "Border image slice",
                                                               "Border image slice",
                                                               GTK_TYPE_BORDER, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("border-image-width",
+                                                              "Border image width",
+                                                              "Border image width",
+                                                              GTK_TYPE_BORDER, 0));  
   _gtk_style_property_register           (g_param_spec_boxed ("border-image",
                                                               "Border Image",
                                                               "Border Image",